from insts.inst import NoOperandInstruction
from jthread.frame import JFrame


class XSTORE(NoOperandInstruction):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"

    def execute(self, frame: JFrame):
        stack = frame.getOperandStack()
        ref = None
        index = None
        arrRef = None
        if self.kind == "int":
            ref = stack.popInt()
            index = stack.popInt()
            arrRef = stack.popRef()
        elif self.kind == "float":
            ref = stack.popFloat()
            index = stack.popInt()
            arrRef = stack.popRef()
        elif self.kind == "double":
            ref = stack.popDouble()
            index = stack.popInt()
            arrRef = stack.popRef()
        elif self.kind == "long":
            ref = stack.popLong()
            index = stack.popInt()
            arrRef = stack.popRef()
        else:
            ref = stack.popRef()
            index = stack.popInt()
            arrRef = stack.popRef()
        if arrRef is None:
            raise Exception("NullPointerException")
        refs = arrRef.bytes()
        if index < 0 or index >= len(refs):
            raise Exception("ArrayIndexOutOfBoundsException")
        refs[index] = ref


class AASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "ref"


class IASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class LASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "long"


class DASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "double"


class BASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


def CASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class SASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class FASTORE(XSTORE):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "float"